package world.criver.h50529.function;

import world.criver.h50529.data.daControllers;
import world.criver.h50529.data.daData;
import world.criver.h50529.data.daFun;
import world.criver.h50529.enums.enumComType;
import world.criver.h50529.module.moEvent;
import world.criver.h50529.module.moGroup;
import world.criver.h50529.module.moGroupEvent;
import world.criver.h50529.module.moGroupItem;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Timer;
import java.util.TimerTask;

public class funGroup {
    private ArrayList<item> items=new ArrayList<>();
    private funMessageFormat funMessageFormat=new funMessageFormat();
    public void updateName(String old_name,String new_name){
        for(int i=0;i<items.size();i++)
            if(items.get(i).getName().equals(old_name))items.get(i).setName(new_name);
    }
    public void startListen(){
        try{
            for(moGroup group: daData.groups)items.add(new item(group.getName(), group.getPort()));
        }catch (Exception e){
            throw new RuntimeException(e);
        }
    }
    public void stopListen(){
        try{
            for(item ii:items)ii.close();
            items.clear();
        }catch (Exception e){
            throw new RuntimeException(e);
        }
    }
    public class item{
        private String name;
        private ServerSocket server;
        private Thread thread;
        private HashMap<Socket,Thread> clients;
        private String data;
        public void close(){
            for(Thread th: clients.values())th.interrupt();
            for(Socket so: clients.keySet()) {
                try {
                    so.close();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
            clients.clear();
            try {
                server.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }

        public item(String name,int port){
            this.name=name;
            clients=new HashMap<>();
            try{
                if(daData.use_port.contains(port))return;
                server=new ServerSocket(port);
                daData.use_port.add(port);
                thread=Thread.startVirtualThread(()->{
                    while(!thread.isInterrupted()){
                        try {
                            Socket client = server.accept();
                            daControllers.page1.addTip(client.getInetAddress().getHostAddress()+">客户端 "+client.getInetAddress().getHostAddress()+" 已连接。");
                            clients.put(client,Thread.startVirtualThread(()->{
                                try {
                                    InputStream in = client.getInputStream();
                                    byte[] bs=new byte[2048];
                                    int length=0;
                                    InputStreamReader re=new InputStreamReader(in);
                                    BufferedReader br=new BufferedReader(re);
                                    while((length=in.read(bs))!=-1){
                                        data=new String(bs,0,length);
                                        System.out.println(data);
                                        if(data==null || data.isEmpty())continue;
                                        ArrayList<moGroup> mgs=daFun.funData.getGroups(port);
                                        daControllers.page1.addTip("收到转发>" + client.getInetAddress().getHostAddress() + ">指令：" + data + " 。");
                                        int num=0;
                                        for(moGroup mg:mgs) {
                                            //moGroup mg= daFun.funData.getGroup(name);
                                            String com = mg.getCommand();
                                            if (mg.getCommandType().equals("hex"))
                                                com = funMessageFormat.hexToString(com);
                                            if (com.equals(data)) {
                                                num++;
                                                for (moGroupEvent event : mg.getItems()) {
                                                    new Timer().schedule(new TimerTask() {
                                                        @Override
                                                        public void run() {
                                                            moEvent moe = daFun.funData.getEvent(event.getName());
                                                            if (moe == null) return;
                                                            if (moe.getCommunication_mode().toLowerCase().equals(enumComType.com3.name()))
                                                                new funSerial().send(moe);
                                                            else if (moe.getCommunication_mode().toLowerCase().equals(enumComType.wol.name()))
                                                                new funWol().send(moe);
                                                            else if (moe.getCommunication_mode().toLowerCase().equals(enumComType.tcp.name()))
                                                                new funTcp().send(moe);
                                                            else if (moe.getCommunication_mode().toLowerCase().equals(enumComType.udp.name()))
                                                                new funUdp().send(moe);
                                                            else {
                                                                daControllers.page1.addTip("转发失败>" + client.getInetAddress().getHostAddress() + ">" + moe.getName() + "(" + moe.getMessage_type().toUpperCase() + ")");
                                                                return;
                                                            }
                                                            daControllers.page1.addTip("完成转发>" + client.getInetAddress().getHostAddress() + ">" + moe.getName() + "(" + moe.getMessage_type().toUpperCase() + ")");
                                                        }
                                                    }, (long) (event.getWait() * 1000));
                                                }
                                            } else {

                                            }
                                        }
                                        if(num==0)daControllers.page1.addTip("收到转发>未找到对应指令，结束转发。");
                                        //else daControllers.page1.addTip("收到转发>已经转发结束。");
                                    }
                                    br.close();
                                    re.close();
                                    in.close();
                                    daControllers.page1.addTip(client.getInetAddress().getHostAddress()+">断开连接。");
                                    clients.remove(client);
                                }catch (Exception e){
                                    throw new RuntimeException(e);
                                }
                            }));
                        }catch (Exception e){
                            if (!(e instanceof java.net.SocketException && "Socket closed".equals(e.getMessage()))) {
                                e.printStackTrace();
                            }
                            thread.interrupt();
                        }
                    }
                });
            }catch (Exception e){
                daControllers.page1.addTip(name+"转发监听启动失败。");
                throw new RuntimeException(e);
            }
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public ServerSocket getServer() {
            return server;
        }

        public void setServer(ServerSocket server) {
            this.server = server;
        }

        public Thread getThread() {
            return thread;
        }

        public void setThread(Thread thread) {
            this.thread = thread;
        }
    }
}
